use std::{net::SocketAddr, sync::Arc, time::Duration};

use crate::api::prelude::*;
use axum::extract::{
    ConnectInfo,
    ws::{Message, WebSocket},
};
use carpet::{
    base::error::{MapServerError, ServerError},
    server::handler::origin_ws_upgrade,
};
use futures::{SinkExt, StreamExt};
use template_api::api::demo::ws::*;
use tokio::{spawn, sync::RwLock};

#[derive(Debug, Handler)]
pub struct HandlerImpl {
    pub conn_info: ConnectInfo<SocketAddr>,
}

#[impl_handler(HandleDef_)]
impl HandlerImpl {
    async fn _handle(
        self,
        upgrade: WsUpgrade<SendMessage, ReceiveMessage, i32, i32>,
        data: Query<RequestData>,
    ) -> Result<WsResponse, ServerError> {
        let websocket = origin_ws_upgrade(upgrade).map_server_error::<ServerError>()?;
        let response = websocket.on_upgrade(async move |ws| {
            self.handle_ws(ws, data.0).await;
        });
        Ok(WsResponse {
            response: Box::new(response),
        })
    }
}

impl HandlerImpl {
    async fn handle_ws(self, websocket: WebSocket, data: RequestData) {
        let (tx, mut rx) = websocket.split();
        let tx = Arc::new(RwLock::new(tx));
        let task_tx = tx.clone();
        spawn(async move {
            let tx = task_tx;
            let mut count = 0;
            loop {
                if count > 10 {
                    break;
                }
                let text = serde_json::to_string(&ReceiveMessage {
                    content: data.title.clone(),
                });
                let text = match text {
                    Ok(text) => text,
                    Err(e) => {
                        error!("Error serializing message: {}", e);
                        break;
                    }
                };
                let msg = Message::Text(text.into());
                let result = tx.write().await.send(msg).await;
                if let Err(e) = result {
                    error!("Error sending message: {}", e);
                    break;
                }
                count += 1;
                tokio::time::sleep(Duration::from_secs(1)).await;
            }
        });
        while let Some(msg) = rx.next().await {
            let msg = match msg {
                Ok(msg) => msg,
                Err(e) => {
                    error!("Error receiving message: {}", e);
                    break;
                }
            };
            let result = tx.write().await.send(msg).await;
            match result {
                Ok(_) => {
                    info!("Message sent successfully");
                }
                Err(e) => {
                    error!("Error sending message: {}", e);
                    break;
                }
            }
        }
        if let Err(e) = tx.write().await.close().await {
            println!("Error closing connection: {}", e);
        }
    }
}
